package chat.client.service;

import chat.client.view.ClientView;
import chat.tools.ServiceTools;
import chat.tools.TimerTools;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端功能实现类
 *
 * @author 谈笑、
 * @dateTime 2020/10/22 19:52
 */
public class ClientCore implements Runnable {

    // 客户端窗体
    private ClientView clientView;


    // 连接时长计时器
    private TimerTools timerTools;


    // 客户端套接字
    private Socket socket;


    // 报文数据输出流
    private DataOutputStream dataOutputStream;


    // 客户端名称
    private String clientName;

    private String imgUrl;


    // 客户端运行状态
    private boolean isClientCoreRun = false;


    public ClientCore() {
    }


    // 客户端初始化成员属性
    public ClientCore(ClientView clientView, String clientName) {
        this.clientView = clientView;
        this.clientName = clientName;
    }


    /**
     * 连接服务器
     * <p>
     * #1 连接到指定IP地址和端口的服务器
     */
    public boolean connectServer(String ip, int port) {
        try {
            // 连接到指定的服务器
            this.socket = new Socket(InetAddress.getByName(ip), port);

            // 修改客户端连接状态
            this.isClientCoreRun = true;

            // 实例化报文输出流
            this.dataOutputStream = new DataOutputStream(this.socket.getOutputStream());

            // 向服务器发送连接客户端的名称
            this.dataOutputStream.writeUTF(this.clientName);

            // 清空报文缓存
            this.dataOutputStream.flush();

            // 连接服务器成功
            return true;

        } catch (Exception e) {
            e.printStackTrace();
            // 连接服务器失败
            return false;
        }
    }


    /**
     * 发送报文
     * <p>
     * #1 将客户端输入的报文发送到服务器
     */
    public void sengMsg(String msg) {
        try {
            // 发送报文
            this.dataOutputStream.writeUTF(msg);

            // 清空缓存
            this.dataOutputStream.flush();

        } catch (IOException e) {
            e.printStackTrace();
            this.closeClientConnect();
        }
    }


    /**
     * 断开客户端与服务端的连接
     */
    public void closeClientConnect() {
        if (this.dataOutputStream != null) {
            try {
                // 结束连接时长计时
                this.timerTools.setTimerToolsRun();

                // 关闭输入流
                this.dataOutputStream.close();

                // 结束客户端线程运行
                this.isClientCoreRun = false;

                // 断开客户端套接字
                if (this.socket != null) {
                    this.socket.close();
                }

                // 清空在线用户列表
                clientView.getDefaultListModel().clear();

                // 添加消息记录
                this.clientView.getjTextAreas()[0].append("[系统通知 "
                        + ServiceTools.getCurrentDateTime() + "]：本端与服务器断开连接\n");

                // 修改客户端窗体样式
                ServiceTools.setStopClientWindowStyle(this.clientView);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * 设置客户端运行状态
     */
    public synchronized void setClientCoreRun() {
        this.isClientCoreRun = false;
    }


    /**
     * 设置计时器运行状态
     */
    public void setTimerTools(TimerTools timerTools) {
        this.timerTools = timerTools;
    }


    /**
     * 返回客户端运行状态
     */
    public boolean getClientCoreRun() {
        return this.isClientCoreRun;
    }


    @Override
    public void run() {
        // 创建接收报文线程类
        ReceiveMsg receiveMsg = new ReceiveMsg();

        // 启动该线程
        new Thread(receiveMsg).start();
    }


    /**
     * 接收报文线程类
     */
    class ReceiveMsg implements Runnable {

        // 输入输如流
        private DataInputStream dataInputStream;

        public ReceiveMsg() {
            try {
                // 数据输入流
                this.dataInputStream = new DataInputStream(socket.getInputStream());
            } catch (IOException e) {
                e.printStackTrace();
                closeClientConnect();
            }
        }


        /**
         * 分析报文数据
         */
        public void analysisMsg(String msg) {
            // 报文数据必须大于所有定义的作用符
            if (msg.length() > 23) {

                // 所有在线客户端报文
                if ("#Z_X_K_H_D#".equals(msg.substring(0, 11))) {

                    // 获取到所有在线的客户端名称
                    String[] allClient = msg.split("\\*K_G\\*")[1].split("\\$A_N_D\\$");

                    // 清空在线用户列表
                    clientView.getDefaultListModel().clear();

                    // 设置列表内容
                    for (String name : allClient) {
                        // 添加每一个在线的客户端
                        clientView.getDefaultListModel().addElement(name);
                    }
                    return;
                }
            }

            // 普通报文
            clientView.getjTextAreas()[0].append(msg + "\n");
        }


        @Override
        public void run() {
            try {
                // 客户端在运行才能接收报文
                while (isClientCoreRun) {
                    // 接收到报文
                    String msg = this.dataInputStream.readUTF();

                    // 分析报文
                    this.analysisMsg(msg);
                }
            } catch (IOException e) {
                // 发生异常，一般是服务端停止服务。
                e.printStackTrace();
                closeClientConnect();
            }
        }

    }

}